package com.github.bitsapling.sapling.service.impl;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.bitsapling.sapling.mapper.*;
import com.github.bitsapling.sapling.entity.Permission;
import com.github.bitsapling.sapling.entity.PromotionPolicy;
import com.github.bitsapling.sapling.entity.User;
import com.github.bitsapling.sapling.entity.UserGroup;
import com.github.bitsapling.sapling.controller.bo.UserBO;
import com.github.bitsapling.sapling.controller.dto.UserResponseDTO;
import com.github.bitsapling.sapling.controller.dto.UserSessionResponseDTO;
import com.github.bitsapling.sapling.service.UserService;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;


@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UserMapper userMapper;

    @Resource
    private UserMapperCustom userMapperCustom;

    @Resource
    private UserGroupMapper userGroupMapper;

    @Resource
    private PromotionPolicyMapper promotionPolicyMapper;

    @Override
    public User createOrUpdate(User user) {
        if(user.getId() == null) {
            userMapper.insert(user);
        }else{
            userMapper.updateById(user);
        }
        return user;
    }

    @Override
    public User getUserById(long id) {
        return userMapper.selectById(id);
    }

    @Override
    public User getUserByUsername(String username) {
        return userMapper.selectOne(
                new QueryWrapper<User>().eq("username", username)
        );
    }

    @Override
    public User getUserByEmail(String email) {
        return userMapper.selectOne(
                new QueryWrapper<User>().eq("email", email)
        );
    }

    @Override
    public User getUserByPasskey(String passkey) {
        return userMapper.selectOne(
                new QueryWrapper<User>().eq("passkey", passkey)
        );
    }

    @Override
    public UserSessionResponseDTO getUserSessionResponseDTO(User user) {
        Map<String, Object> map = new HashMap<>();
        if (user.getId() != null) {
            map.put("id", user.getId());
        }
        UserResponseDTO userResponseDTO =  userMapperCustom.getUserResponseDTOById(map);

        SaTokenInfo tokenInfo = null;
        try {
            tokenInfo = StpUtil.getTokenInfo();
        } catch (NotLoginException ignored) {
            // 忽略未登录异常
        }
        return new UserSessionResponseDTO(tokenInfo, userResponseDTO);
    }

    @Override
    public String getPasskeyById(long id) {
        User user = userMapper.selectOne(
                new QueryWrapper<User>().eq("id", id)
        );
        return user.getPasskey();
    }

    @Override
    public long calculatePromotionUploadOffset(long userId, long lastDownload) {
        User user = userMapper.selectById(userId);
        if (user == null) {
            return 0;
        }
        UserGroup userGroup = userGroupMapper.selectById(user.getGroupId());
        if (userGroup == null) {
            return 0;
        }
        PromotionPolicy promotionPolicy = promotionPolicyMapper.selectById(userGroup.getPromotionPolicyId());
        if (promotionPolicy == null) {
            return 0;
        }
        return (long) promotionPolicy.applyUploadRatio(lastDownload);
    }

    @Override
    public long calculatePromotionDownloadOffset(long userId, long lastUploaded) {
        User user = userMapper.selectById(userId);
        if (user == null) {
            return 0;
        }
        UserGroup userGroup = userGroupMapper.selectById(user.getGroupId());
        if (userGroup == null) {
            return 0;
        }
        PromotionPolicy promotionPolicy = promotionPolicyMapper.selectById(userGroup.getPromotionPolicyId());
        if (promotionPolicy == null) {
            return 0;
        }
        return (long) promotionPolicy.applyDownloadRatio(lastUploaded);
    }

    @Override
    public List<User> getAllUsers() {
        return userMapper.selectList(null);
    }

    public boolean deleteUser(User user) {
        return userMapper.deleteById(user.getId()) > 0;
    }

    @Override
    public long getPromotionDownloadOffset(long userId) {
        User user = userMapper.selectById(userId);
        return user.getDownloaded();
    }

    @Override
    public long getPromotionUploadOffset(long userId) {
        User user = userMapper.selectById(userId);
        return user.getUploaded();
    }

    public float calculateShaereIndex(long userId) {
        User user = userMapper.selectById(userId);
        float download= user.getDownloaded();
        float upload= user.getRealUploaded();
        if (download ==0 ) {
            return 0;
        }
        if (upload/download >3) {
            return 3;
        }
        if (download/upload <0) {
            return 0;
        }
        return  upload /download;
    }

    public float calculateMagicIndex(long userId) {
        User user = userMapper.selectById(userId);
        float seedingtime= (float) user.getSeedingTime() /1000/60/60; //小时制
        if (seedingtime < 0){
            return 0;
        }
        if(seedingtime>50){
            return 50;
        }

        return seedingtime;
    }
}
